# coding: utf-8

from daedalus.celery import app

from jobs.models import TaskLog, TaskHostLog
from .worker.base import run_task as worker_run_task
from . import constants as task_status


@app.task
def run_task(task_log_id, celery_id):
    '''
    加载task任务
        0. 获取要执行的任务
        1. 加载要执行的主机
            选择调度策略
        2. 加载要执行的任务
        3. 调度任务
        4. 存储任务结果

    思路2:
        scheduler监听在scheduler调度队列
        shceduler:
            根据传递进来的主机进行拆分, 分成几组目标主机
            将分完的组的目标主机+任务参数进行拼接,发送到celery的task任务队列
            scheduler这个地方可能会失败:
                如果任务失败了,则重新执行的时候需要确保任务不会被反复执行:
                    如果是一个playbook可能会有多个任务,要确保能检测到这个地方任务的执行状态
                        如果一个playbook执行了一半,并且当前仍在继续执行,则不进行处理
                        如果一个playbook执行完成,则也忽略掉该主机
                如果scheduler的worker挂掉了,则回复的时候需要查看下面的worker是否挂掉,如果没有挂掉,则任务可以继续执行
                    如果下面的任务仍然在继续执行则这个地方不进行处理
        worker:
            根据接收的任务来进行批量的执行
            任务的结果返回给scheduler的任务id
        scheduler监听在消息队列中,定时的去轮训任务的结果同时将结果保存到数据库中
        前端通过ajax去定时轮训数据库中的任务执行情况

    实现的:
        暂时没有加入调度模块
        直接使用worker去执行任务
        如果任务执行的时候，发现之前主机的任务状态不在QUEUE，则把任务的状态置为失败
    '''
    task_log = TaskLog.objects.get(id=task_log_id)
    task_log.celery_task_id = celery_id
    task_log.status = task_status.STARTED
    task_log.save()

    hosts = task_log.hosts.split(',')
    if task_log and hosts:
        status, output = worker_run_task(task_log_id, hosts)
        # 获取所有主机的状态集合
        hosts_status = set([host.status for host in TaskHostLog.objects.filter(task_log_id=task_log.id).all()])
        if hosts_status.issubset(task_status.SUCCESS_STATUS):
            task_log.status = task_status.SUCCESS
        else:
            task_log.status = task_status.FAILURE
        task_log.output = output
        task_log.save()

        return status, output
